using System;
using System.Globalization;
using System.Reflection;
using System.Reflection.Emit;

namespace RaisingStudio.SmallBasicCompiler.Expressions
{
    [Serializable]
    public class BinaryExpression : Expression
    {
        public Expression LeftHandSide
        {
            get;
            set;
        }
        public TokenInfo Operator
        {
            get;
            set;
        }
        public Expression RightHandSide
        {
            get;
            set;
        }
        public override void AddSymbols(SymbolTable symbolTable)
        {
            if (this.LeftHandSide != null)
            {
                this.LeftHandSide.AddSymbols(symbolTable);
            }
            if (this.RightHandSide != null)
            {
                this.RightHandSide.AddSymbols(symbolTable);
            }
        }
        public override void EmitIL(CodeGenScope scope)
        {
            MethodInfo methodInfo = null;
            switch (this.Operator.Token)
            {
                case Token.And:
                    {
                        methodInfo = scope.TypeInfoBag.And;
                        break;
                    }
                case Token.Equals:
                    {
                        methodInfo = scope.TypeInfoBag.EqualTo;
                        break;
                    }
                case Token.Or:
                    {
                        methodInfo = scope.TypeInfoBag.Or;
                        break;
                    }
                case Token.Addition:
                    {
                        methodInfo = scope.TypeInfoBag.Add;
                        break;
                    }
                case Token.Subtraction:
                    {
                        methodInfo = scope.TypeInfoBag.Subtract;
                        break;
                    }
                case Token.Division:
                    {
                        methodInfo = scope.TypeInfoBag.Divide;
                        break;
                    }
                case Token.Multiplication:
                    {
                        methodInfo = scope.TypeInfoBag.Multiply;
                        break;
                    }
                case Token.LessThan:
                    {
                        methodInfo = scope.TypeInfoBag.LessThan;
                        break;
                    }
                case Token.LessThanEqualTo:
                    {
                        methodInfo = scope.TypeInfoBag.LessThanOrEqualTo;
                        break;
                    }
                case Token.GreaterThan:
                    {
                        methodInfo = scope.TypeInfoBag.GreaterThan;
                        break;
                    }
                case Token.GreaterThanEqualTo:
                    {
                        methodInfo = scope.TypeInfoBag.GreaterThanOrEqualTo;
                        break;
                    }
                case Token.NotEqualTo:
                    {
                        methodInfo = scope.TypeInfoBag.NotEqualTo;
                        break;
                    }
            }
            this.LeftHandSide.EmitIL(scope);
            this.RightHandSide.EmitIL(scope);
            scope.ILGenerator.EmitCall(OpCodes.Call, methodInfo, null);
        }
        public override string ToString()
        {
            return string.Format(CultureInfo.CurrentUICulture, "({0} {1} {2})", new object[]
			{
				this.LeftHandSide, 
				this.Operator.Text, 
				this.RightHandSide
			});
        }
    }
}
